from socket import *
import threading
from tqdm import tqdm, trange
from concurrent.futures import ThreadPoolExecutor
from concurrent.futures._base import Future

lock = threading.Lock()         # 线程锁
openNum=0                       # 端口开发数量统计
threads = []                    # 线程池
pool = ThreadPoolExecutor(100)  # 固定长度线程池
open_port = []                  # 打开端口列表
port_scan_range = 65535         # 端口扫描范围 0~port_scan_range
pbar = tqdm(range(port_scan_range),desc="port scanner : ") # 进度条

def port_scanner(host, port):
    global openNum
    try:
        s = socket(AF_INET, SOCK_STREAM)
        s.connect((host, port))
        lock.acquire()
        openNum += 1
        open_port.append(port)
        lock.release()
        s.close()
        return port
    except:
        pass

def done(res: Future):
    pbar.update()
    port = res.result()
    if port != None:
        print(f"open {port}")

def main(ip, ports=range(port_scan_range)):
    setdefaulttimeout(1)
    #for port in tqdm(ports,desc="port scanner submit: "):
    for port in ports:
        future = pool.submit(port_scanner, ip, port)
        future.add_done_callback(done)
        #t = threading.Thread(target=port_scanner, args=(ip, port))
        #threads.append(t)
        #t.start()
    #for t in threads:
        #t.join()
    pool.shutdown()
    print(f"PostScan is finish, OpenNum is {openNum}")
    for port in open_port:
        print(f"{ip} {port}")

if __name__ == '__main__':
    ip="jasonpg-space"
    main(ip)


